/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

/*
 * CgcGuiMain.java
 *
 * Created on 22/06/2010, 16:20:50
 */
package gui;

import ConsultaURL.URLCommunication;
import corretorgramatical.Palavra;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JFileChooser;
import javax.swing.JOptionPane;
import javax.swing.JTextArea;
import javax.swing.event.CaretEvent;
import javax.swing.event.CaretListener;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.text.BadLocationException;
import javax.swing.text.Element;
import javax.swing.text.JTextComponent;
import javax.swing.text.Utilities;
import lexico.*;
import persistencia.DatabaseCommunication;
import sintatico.*;
import speech.Sintetizador;

/**
 *
 * @author Marcello
 */
public class CgcGuiMain extends javax.swing.JFrame {

    private AnalisadorLexico lexico;
    //private AnalisadorSintatico sintatico;
    private URLCommunication urlComunic;
    private DatabaseCommunication dbComunic;
    private String descricaoDoErro = "";
    private String palavraErrada = "";
    private String nomeArquivo = "";
    private CaretAux caretAux;
    private final double timeout = 3;
    private double tempoAtual = 0;
    private double tempoUltimaDigitacao = 0;
    boolean analisarNovamente = false;
    private Thread monitorDigitacao;
    Sintetizador sintetizador;
    boolean corrigindo = false;
    private int tamanhoTexto = 0;
    private int ultimaPontuacao = -1;
    File ultimoDiretorio;


    /** Creates new form CgcGuiMain */
    public CgcGuiMain(URLCommunication urlComunic, DatabaseCommunication dbComunication) {
        initComponents();

        this.urlComunic = urlComunic;
        this.dbComunic = dbComunication;

        lexico = CriadorLexicoPT.criaAutomatoLexicoPT(urlComunic, dbComunication);
        //sintatico = new AnalisadorSintatico();
        ultimoDiretorio = null;
        caretAux = new CaretAux();
        jTextArea1.addCaretListener(caretAux);
        jTextArea1.getDocument().addDocumentListener(new DocumentListener() {

            public void changedUpdate(DocumentEvent e) {
            }

            public void insertUpdate(DocumentEvent e) {
                tempoUltimaDigitacao = System.currentTimeMillis();
                //System.out.println("insertUpdate: Added " + e.getLength()
                //        + " characters, document length = " + e.getDocument().getLength()
                //        + " offset: " + e.getOffset());

                if (!corrigindo && e.getDocument().getLength() - e.getLength() != e.getOffset()) {
                    analisarNovamente = true;
                }

                if (!corrigindo && !analisarNovamente) {
                    lexico.setRetornoRemove(false);
                    if (e.getLength() > 1) {
                        int inicio = e.getDocument().getLength() - e.getLength();
                        int fim = e.getDocument().getLength();
                        String aux = "";
                        try {
                            aux = e.getDocument().getText(0, fim);
                        } catch (BadLocationException ex) {
                            Logger.getLogger(CgcGuiMain.class.getName()).log(Level.SEVERE, null, ex);
                        }
                        while (inicio < fim) {
                            if (aux.length() <= inicio) {
                                break;
                            }
                            //System.out.println("Enviando " + aux.charAt(inicio));
                            enviaParaOLexico(aux.charAt(inicio), caretAux.linhaAtual, false);
                            inicio++;
                        }

                        // manda um espaco para avaliar uma possivel palavra restante no lexico
                        // e envia a mensagem de erro se houver
                        enviaParaOLexico(' ', caretAux.linhaAtual, false);

                        if (palavraErrada.length() > 0) {
                            System.out.println("Desconhecido " + palavraErrada);
                            //palavraErrada = lexico.getPalavraErrada();
                            String msg;
                            msg = jTextArea2.getText();
                            if (descricaoDoErro.length() == 0) {
                                msg += Hora.horaAtual() + ": Palavra desconhecida: \"" + palavraErrada + "\". F1 para corrigir.\n";
                                jTextArea2.setText(msg);
                                Sintetizador.speak("Palavra desconhecida: " + palavraErrada);
                                Sintetizador.speak("F1 para corrigir.");
                            } else {
                                msg += Hora.horaAtual() + ": " + descricaoDoErro + " F1 para corrigir.\n";
                                jTextArea2.setText(msg);
                                Sintetizador.speak(descricaoDoErro);
                                Sintetizador.speak("F1 para corrigir.");
                            }

                        }
                    }
                }

                tamanhoTexto = e.getDocument().getLength();
            }

            public void removeUpdate(DocumentEvent e) {
                tempoUltimaDigitacao = System.currentTimeMillis();
                //System.out.println("removeUpdate: Removed " + e.getLength()
                //        + " characters, document length = " + e.getDocument().getLength() + " offset" + e.getOffset());

                if (!corrigindo && e.getDocument().getLength() != e.getOffset()) {
                    analisarNovamente = true;
                }

                if (!corrigindo && !analisarNovamente && tamanhoTexto > e.getDocument().getLength()) {
                    int aux = tamanhoTexto - e.getDocument().getLength();

                    while (aux > 0) {
                        if (lexico.removeUmCaractere()) {
                            System.out.println("Analisando novamente");
                            analisarNovamente = true;
                            break;
                        }
                        System.out.println(lexico.getPalavraAtual());
                        aux--;
                    }
                }

                tamanhoTexto = e.getDocument().getLength();
            }
        });
        sintetizador = new Sintetizador();

        monitorDigitacao = monitorDigitacao(this);
        monitorDigitacao.start();
    }
//
//    public CgcGuiMain(AnalisadorLexico lexico, AnalisadorSintatico sintatico) {
//        initComponents();
//        this.lexico = lexico;
//        this.sintatico = sintatico;
//
//        ultimoDiretorio = null;
//        caretAux = new CaretAux();
//        jTextArea1.addCaretListener(caretAux);
//        sintetizador = new Sintetizador();
//    }

    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        jScrollPane1 = new javax.swing.JScrollPane();
        jTextArea1 = new javax.swing.JTextArea();
        jScrollPane2 = new javax.swing.JScrollPane();
        jTextArea2 = new javax.swing.JTextArea();
        jLabel1 = new javax.swing.JLabel();
        jButton2 = new javax.swing.JButton();
        jButton3 = new javax.swing.JButton();
        jButton4 = new javax.swing.JButton();
        jLabel2 = new javax.swing.JLabel();
        jSeparator1 = new javax.swing.JSeparator();
        jMenuBar1 = new javax.swing.JMenuBar();
        jMenu1 = new javax.swing.JMenu();
        jMenuItem1 = new javax.swing.JMenuItem();
        jMenuItem2 = new javax.swing.JMenuItem();
        jMenuItem3 = new javax.swing.JMenuItem();
        jMenuItem4 = new javax.swing.JMenuItem();
        jMenu2 = new javax.swing.JMenu();
        jMenuItem6 = new javax.swing.JMenuItem();
        jMenuItem7 = new javax.swing.JMenuItem();
        jMenuItem8 = new javax.swing.JMenuItem();

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
        setTitle("Corretor Gramatical para Deficientes Visuais");

        jTextArea1.setColumns(20);
        jTextArea1.setLineWrap(true);
        jTextArea1.setRows(5);
        jTextArea1.setWrapStyleWord(true);
        jTextArea1.addKeyListener(new java.awt.event.KeyAdapter() {
            public void keyTyped(java.awt.event.KeyEvent evt) {
                jTextArea1KeyTyped(evt);
            }
        });
        jScrollPane1.setViewportView(jTextArea1);

        jTextArea2.setColumns(20);
        jTextArea2.setLineWrap(true);
        jTextArea2.setRows(5);
        jTextArea2.setWrapStyleWord(true);
        jScrollPane2.setViewportView(jTextArea2);

        jLabel1.setText("Saída do Corretor");

        jButton2.setText("Corrigir Erro [ F1 ]");
        jButton2.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jButton2ActionPerformed(evt);
            }
        });

        jButton3.setText("Reproduzir Descrição do Erro [ F2 ]");
        jButton3.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jButton3ActionPerformed(evt);
            }
        });

        jButton4.setText("Analisar Texto Completo [ F3 ]");
        jButton4.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jButton4ActionPerformed(evt);
            }
        });

        jLabel2.setText("Entrada de Texto");

        jMenu1.setText("Arquivo");

        jMenuItem1.setAccelerator(javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_N, java.awt.event.InputEvent.CTRL_MASK));
        jMenuItem1.setText("Novo");
        jMenuItem1.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jMenuItem1ActionPerformed(evt);
            }
        });
        jMenu1.add(jMenuItem1);

        jMenuItem2.setAccelerator(javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_O, java.awt.event.InputEvent.CTRL_MASK));
        jMenuItem2.setText("Abrir");
        jMenuItem2.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jMenuItem2ActionPerformed(evt);
            }
        });
        jMenu1.add(jMenuItem2);

        jMenuItem3.setAccelerator(javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_S, java.awt.event.InputEvent.CTRL_MASK));
        jMenuItem3.setText("Salvar");
        jMenuItem3.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jMenuItem3ActionPerformed(evt);
            }
        });
        jMenu1.add(jMenuItem3);

        jMenuItem4.setAccelerator(javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_Q, java.awt.event.InputEvent.CTRL_MASK));
        jMenuItem4.setText("Sair");
        jMenu1.add(jMenuItem4);

        jMenuBar1.add(jMenu1);

        jMenu2.setText("Editar");

        jMenuItem6.setAccelerator(javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_F1, 0));
        jMenuItem6.setText("Corrigir Erro");
        jMenuItem6.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jMenuItem6ActionPerformed(evt);
            }
        });
        jMenu2.add(jMenuItem6);

        jMenuItem7.setAccelerator(javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_F2, 0));
        jMenuItem7.setText("Reproduzir Descrição do Erro");
        jMenuItem7.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jMenuItem7ActionPerformed(evt);
            }
        });
        jMenu2.add(jMenuItem7);

        jMenuItem8.setAccelerator(javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_F3, 0));
        jMenuItem8.setText("Corrigir Texto Completo");
        jMenuItem8.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jMenuItem8ActionPerformed(evt);
            }
        });
        jMenu2.add(jMenuItem8);

        jMenuBar1.add(jMenu2);

        setJMenuBar(jMenuBar1);

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
                    .addComponent(jSeparator1, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, 794, Short.MAX_VALUE)
                    .addComponent(jScrollPane1, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, 794, Short.MAX_VALUE)
                    .addComponent(jScrollPane2, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, 794, Short.MAX_VALUE)
                    .addComponent(jLabel1, javax.swing.GroupLayout.Alignment.LEADING)
                    .addGroup(javax.swing.GroupLayout.Alignment.LEADING, layout.createSequentialGroup()
                        .addComponent(jButton2)
                        .addGap(18, 18, 18)
                        .addComponent(jButton3)
                        .addGap(18, 18, 18)
                        .addComponent(jButton4))
                    .addComponent(jLabel2, javax.swing.GroupLayout.Alignment.LEADING))
                .addContainerGap())
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
                .addContainerGap()
                .addComponent(jLabel2)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 372, Short.MAX_VALUE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(jButton2)
                    .addComponent(jButton3)
                    .addComponent(jButton4))
                .addGap(15, 15, 15)
                .addComponent(jSeparator1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addGap(3, 3, 3)
                .addComponent(jLabel1)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(jScrollPane2, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addContainerGap())
        );

        pack();
    }// </editor-fold>//GEN-END:initComponents

    private void jButton3ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton3ActionPerformed
        System.out.println("reproduzir descricao de erro");

        if (palavraErrada.length() > 0) {
            if (descricaoDoErro.length() > 0)
                Sintetizador.speak(descricaoDoErro);
            else
                Sintetizador.speak("Palavra desconhecida: " + palavraErrada);
            Sintetizador.speak("F1 para corrigir.");
        } else {
            Sintetizador.speak("Não há mensagem de erro.");
            String msg = jTextArea2.getText();
            msg += Hora.horaAtual() + ": Não há mensagem de erro.\n";
            jTextArea2.setText(msg);
        }
    }//GEN-LAST:event_jButton3ActionPerformed

    private void jButton2ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton2ActionPerformed
        System.out.println("corrigir erro palavra:" + palavraErrada);
        corrigindo = true;

        if (palavraErrada.length() > 0) {
            if (corrigirPalavra(palavraErrada) == 0) {
                palavraErrada = "";
                descricaoDoErro = "";
                analisaTodoOTexto();
            }
        } else {
            Sintetizador.speak("Não há erro para corrigir.");
            String msg = jTextArea2.getText();
            msg += Hora.horaAtual() + ": Não há erro para corrigir.\n";
            jTextArea2.setText(msg);
        }

        corrigindo = false;
    }//GEN-LAST:event_jButton2ActionPerformed

    private void jButton4ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton4ActionPerformed
        System.out.println("corrigir todo o texto");
        analisaTodoOTexto();
    }//GEN-LAST:event_jButton4ActionPerformed

    private void jMenuItem6ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jMenuItem6ActionPerformed
        jButton2ActionPerformed(evt);
    }//GEN-LAST:event_jMenuItem6ActionPerformed

    private void jMenuItem7ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jMenuItem7ActionPerformed
        jButton3ActionPerformed(evt);
    }//GEN-LAST:event_jMenuItem7ActionPerformed

    private void jMenuItem8ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jMenuItem8ActionPerformed
        jButton4ActionPerformed(evt);
    }//GEN-LAST:event_jMenuItem8ActionPerformed

    private void jMenuItem1ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jMenuItem1ActionPerformed
        jTextArea1.setText("");
        jTextArea2.setText("");
        nomeArquivo = "";
        tamanhoTexto = 0;
        tempoAtual = 0;
        tempoUltimaDigitacao = 0;
        ultimaPontuacao = -1;
        palavraErrada = "";
        descricaoDoErro = "";
        analisarNovamente = false;
        corrigindo = false;

        lexico = CriadorLexicoPT.criaAutomatoLexicoPT(urlComunic, dbComunic);
        //sintatico = new AnalisadorSintatico();
    }//GEN-LAST:event_jMenuItem1ActionPerformed

    private void jMenuItem3ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jMenuItem3ActionPerformed

        File arquivo = null;
        PrintWriter arquivoSalvo = null;
        String caminho = "";

        int questao = -1;

        if (nomeArquivo.length() > 0) {
            Object[] opcoes = {"Sim", "Nao", "Cancelar"};
            questao = JOptionPane.showOptionDialog(null, "Deseja sobrescrever o arquivo atual?\n"
                    + "(Sim para sobrescrever / Não para salvar um arquivo diferente)",
                    "Salvar arquivo", JOptionPane.YES_NO_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE,
                    null, opcoes, opcoes[0]);
        }

        if (questao == JOptionPane.CANCEL_OPTION) {
            return;
        }

        if (questao == JOptionPane.YES_OPTION) {
            caminho = nomeArquivo;
        }

        if (questao == JOptionPane.NO_OPTION || nomeArquivo.length() == 0) {
            JFileChooser fc = new JFileChooser();

            // restringe a amostra a diretorios apenas
            fc.setFileSelectionMode(JFileChooser.FILES_ONLY);

            if (ultimoDiretorio != null) {
                fc.setCurrentDirectory(ultimoDiretorio);
            }

            int res = fc.showSaveDialog(null);

            if (res == JFileChooser.APPROVE_OPTION) {
                if (fc.getSelectedFile() == null) {
                    JOptionPane.showMessageDialog(null, "Problema no arquivo escolhido. Impossivel salvar.",
                            "Erro salvando arquivo.", JOptionPane.ERROR_MESSAGE);
                    return;
                }
                arquivo = fc.getSelectedFile();
            } else {
                return;
            }
        }

        try {
            if (arquivo != null) {
                arquivoSalvo = new PrintWriter(new FileWriter(arquivo));
            } else if (caminho.length() > 0) {
                arquivoSalvo = new PrintWriter(new FileWriter(caminho));
            } else {
                JOptionPane.showMessageDialog(null, "Problema no arquivo escolhido. Impossivel salvar.",
                        "Erro salvando arquivo.", JOptionPane.ERROR_MESSAGE);
                return;
            }
        } catch (FileNotFoundException ex) {
            Logger.getLogger(CgcGuiMain.class.getName()).log(Level.SEVERE, null, ex);
        } catch (IOException ex) {
            Logger.getLogger(CgcGuiMain.class.getName()).log(Level.SEVERE, null, ex);
        }
        try {
            int linhas = jTextArea1.getLineCount();

            for (int i = 0; i < linhas; i++) {
                int inicio, fim;
                String linha = "";
                String texto = jTextArea1.getText();

                inicio = jTextArea1.getLineStartOffset(i);
                fim = jTextArea1.getLineEndOffset(i);
                linha = texto.substring(inicio, fim);
                //arquivoSalvo.print(linha);
                if (i < (linhas - 1)) {
                    if (linha.length() == 0) {
                        arquivoSalvo.println();
                    } else {
                        int aux = (int) linha.charAt(linha.length() - 1);
                        if (aux == 10) { // quebra de linha que da pau
                            arquivoSalvo.println(linha.substring(0, linha.length() - 1));
                        } else {
                            arquivoSalvo.println(linha);
                        }
                    }
                } else {
                    arquivoSalvo.print(linha);
                }
                //arquivoSalvo.
                //for (int j = 0; j < )
            }
            arquivoSalvo.close();
            if (arquivo != null) {
                nomeArquivo = arquivo.getAbsolutePath();
                ultimoDiretorio = arquivo;
            }
            JOptionPane.showMessageDialog(null, "Arquivo salvo com sucesso.",
                    "Arquivo salvo.", JOptionPane.INFORMATION_MESSAGE);
        } catch (BadLocationException ex) {
            Logger.getLogger(CgcGuiMain.class.getName()).log(Level.SEVERE, null, ex);
        }
    }//GEN-LAST:event_jMenuItem3ActionPerformed

    private void jMenuItem2ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jMenuItem2ActionPerformed

        JFileChooser fileChooser = new JFileChooser("C:\\");

        fileChooser.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES);

        if (ultimoDiretorio != null) {
            fileChooser.setCurrentDirectory(ultimoDiretorio);
        }

        int result = fileChooser.showOpenDialog(this);

        File arquivo = null;

        if (result == JFileChooser.APPROVE_OPTION) {
            arquivo = ultimoDiretorio = fileChooser.getSelectedFile();
            nomeArquivo = arquivo.getAbsolutePath();
            if (!(arquivo.getName().toLowerCase().endsWith(".txt") || arquivo.getName().toLowerCase().endsWith(".pas")
                    || arquivo.getName().toLowerCase().endsWith(".cpp") || arquivo.getName().toLowerCase().endsWith(".c"))) {
                JOptionPane.showMessageDialog(null, "Arquivo com extensão inválida!");
                return;
            } else {
                jTextArea1.setText("");
            }

            FileReader leitor = null;
            BufferedReader br = null;
            try {
                leitor = new FileReader(arquivo);
                if (leitor != null) {
                    br = new BufferedReader(leitor);
                }
            } catch (FileNotFoundException ex) {
                JOptionPane.showMessageDialog(null, "Erro ao abrir o arquivo!");
                return;
            }

            if (br == null) {
                JOptionPane.showMessageDialog(null, "Problema no arquivo escolhido. Impossivel abrir.",
                        "Erro abrindo arquivo.", JOptionPane.ERROR_MESSAGE);
                return;
            }

            String linha;
            int contadorLinhas = 0;
            corrigindo = true;
            try {
                while ((linha = br.readLine()) != null) {
                    if (++contadorLinhas > jTextArea1.getLineCount()) {
                        jTextArea1.setText(jTextArea1.getText() + "\n");
                    }
                    jTextArea1.setText(jTextArea1.getText() + linha);
                }
                leitor.close();
            } catch (IOException ex) {
                Logger.getLogger(CgcGuiMain.class.getName()).log(Level.SEVERE, null, ex);
            }
            corrigindo = false;
            analisaTodoOTexto();
        }
    }//GEN-LAST:event_jMenuItem2ActionPerformed

    private void jTextArea1KeyTyped(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_jTextArea1KeyTyped
        int resultado = 0;

        if (!evt.isControlDown()) {

            if (!Character.isISOControl(evt.getKeyChar()) || evt.getKeyChar() == '\n') {
                if (!corrigindo && !analisarNovamente)
                    enviaParaOLexico(evt.getKeyChar(), caretAux.linhaAtual);
//                if (evt.getKeyChar() != '\n')
//                    resultado = lexico.consume( evt.getKeyChar() , caretAux.linhaAtual);
//                else
//                    resultado = lexico.consume( ' ' , caretAux.linhaAtual);
//                if (resultado == - 3) {
//                    System.out.println("Desconhecido " + lexico.getPalavraErrada());
//                    palavraErrada = lexico.getPalavraErrada();
//                    Sintetizador.speak("Palavra desconhecida: " + palavraErrada);
//                    Sintetizador.speak("F1 para corrigir.");
//                }
                //jTextArea1.setEditable(true);
            }
        }

        //lexico.imprimeTabela();
        //System.out.println("Linha: " + caretAux.linhaAtual + " Coluna: " + caretAux.colunaAtual);

    }//GEN-LAST:event_jTextArea1KeyTyped

    public void analisaTodoOTexto() {
        lexico.resetaLexico();
        palavraErrada = "";
        descricaoDoErro = "";
        String msg = jTextArea2.getText();
        msg += Hora.horaAtual() + ": Analisando todo o texto.\n";
        jTextArea2.setText(msg);
        String aux = jTextArea1.getText();
        int linha = 1;
        for (int i = 0; i < aux.length(); i++) {
            //System.out.println("Enviando " + aux.charAt(i));
            enviaParaOLexico(aux.charAt(i), linha, false);

            if (aux.charAt(i) == '\n') {
                linha++;
            }
        }

        // manda um espaco para avaliar uma possivel palavra restante no lexico
        // e envia a mensagem de erro se houver
        enviaParaOLexico(' ', caretAux.linhaAtual, false);

        if (palavraErrada.length() > 0) {
            System.out.println("Desconhecido " + palavraErrada);
            //palavraErrada = lexico.getPalavraErrada();
            msg = jTextArea2.getText();
            if (descricaoDoErro.length() == 0) {
                msg += Hora.horaAtual() + ": Palavra desconhecida: \"" + palavraErrada + "\". F1 para corrigir.\n";
                jTextArea2.setText(msg);
                Sintetizador.speak("Palavra desconhecida: " + palavraErrada);
                Sintetizador.speak("F1 para corrigir.");
            } else {
                msg += Hora.horaAtual() + ": " + descricaoDoErro + " F1 para corrigir.\n";
                jTextArea2.setText(msg);
                Sintetizador.speak(descricaoDoErro);
                Sintetizador.speak("F1 para corrigir.");
            }

        }

        lexico.imprimeTabela();
    }

    public int corrigirPalavra(String erro) {
        int lastIndex = jTextArea1.getText().lastIndexOf(erro);
        //jTextArea1.requestFocus();
        if (lastIndex == -1) {
            return -1;
        }

        //jTextArea1.select(lastIndex, jTextArea1.getText().length() - lastIndex);

        String novaPalavra = JOptionPane.showInputDialog(null, "Nova palavra", "Substituição de palavra",
                JOptionPane.PLAIN_MESSAGE);

        //System.out.println("Substituindo " + novaPalavra + " " + lastIndex + " " + palavraErrada.length());
        if (novaPalavra != null) {
            String msg = jTextArea2.getText();
            msg += Hora.horaAtual() + ": Corrigido: \"" + palavraErrada + "\" por \"" + novaPalavra + "\".\n";
            jTextArea2.setText(msg);
            jTextArea1.replaceRange(novaPalavra, lastIndex, lastIndex + palavraErrada.length());
            return 0;
        }
        return -1;
    }

    private Thread monitorDigitacao(CgcGuiMain gui) {
        final CgcGuiMain interfaceAux = gui;
        return new Thread() {

            @Override
            public void run() {
                while (true) {
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException ex) {
                        ex.printStackTrace();
                    }
                    interfaceAux.verificaDigitacao();
                }
            }
        };
    }

    public void verificaDigitacao() {
        this.tempoAtual = System.currentTimeMillis();
        //System.out.println("chamando!");

        if (analisarNovamente && ((this.tempoAtual - this.tempoUltimaDigitacao) / 1000) > this.timeout) {
            analisaTodoOTexto();
            analisarNovamente = false;
        }
    }

    public void enviaParaOLexico(char ch, int linha) {
        enviaParaOLexico(ch, linha, true);
    }

    public void enviaParaOLexico(char ch, int linha, boolean retornaErro) {
        int resultado = 0;
        if (ch != '\n' && ch != '\t') {
            resultado = lexico.consume(ch, linha);
        } else {
            resultado = lexico.consume(' ', linha);
        }
        if (resultado == - 3) {
            System.out.println("Desconhecido " + lexico.getPalavraErrada());
            palavraErrada = lexico.getPalavraErrada();
            if (retornaErro) {
                String msg = jTextArea2.getText();
                msg += Hora.horaAtual() + ": Palavra desconhecida: \"" + palavraErrada + "\". F1 para corrigir.\n";
                jTextArea2.setText(msg);
                Sintetizador.speak("Palavra desconhecida: " + palavraErrada);
                Sintetizador.speak("F1 para corrigir.");
            }

        }

        if (lexico.getUltimaPontuacao() != ultimaPontuacao) {
            if (palavraErrada.length() == 0) { // se nao houver erro do lexico, testa o sintatico
                ArrayList<Palavra> lista = lexico.retornaUltimaExpressao(ultimaPontuacao);
                if (lista != null && lista.size() > 0) {
                    System.out.println("Expressao:");
                    for (int i = 0; i < lista.size(); i++) {
                        System.out.println(lista.get(i));
                    }
                    if (retornaErro)
                        enviaParaOSintatico(lista, true);
                    else enviaParaOSintatico(lista, false);
                } else {
                    System.out.println("Lista vazia na chamada do sintatico!");
                }
            }
            ultimaPontuacao = lexico.getUltimaPontuacao();
        }
    }

    public void enviaParaOSintatico(ArrayList<Palavra> tabela, boolean retornaErro){
        AnalisadorSintatico sint = new AnalisadorSintatico(tabela);
        descricaoDoErro = sint.getLogErro();
        palavraErrada = sint.getPalavraErrada();

        if(!descricaoDoErro.isEmpty() && retornaErro){
            Sintetizador.speak(descricaoDoErro);
            Sintetizador.speak("F1 para corrigir.");
        }
    }

    public void enviaParaOSintatico (ArrayList<Palavra> tabela) {
        enviaParaOSintatico(tabela, true);
    }

    public void setDescricaoDoErro(String str) {
        descricaoDoErro = str;
    }

    public void setPalavraErrada(String str) {
        palavraErrada = str;
    }

    public void atualizarSaida() {
        jTextArea2.setText(descricaoDoErro);
    }

    /**
     * @param args the command line arguments
     */
    public static void main(String args[]) {
        java.awt.EventQueue.invokeLater(new Runnable() {

            public void run() {

                DatabaseCommunication dbc = new DatabaseCommunication();
                URLCommunication urlc = new URLCommunication(dbc);

                new CgcGuiMain(urlc, dbc).setVisible(true);
            }
        });
    }
    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JButton jButton2;
    private javax.swing.JButton jButton3;
    private javax.swing.JButton jButton4;
    private javax.swing.JLabel jLabel1;
    private javax.swing.JLabel jLabel2;
    private javax.swing.JMenu jMenu1;
    private javax.swing.JMenu jMenu2;
    private javax.swing.JMenuBar jMenuBar1;
    private javax.swing.JMenuItem jMenuItem1;
    private javax.swing.JMenuItem jMenuItem2;
    private javax.swing.JMenuItem jMenuItem3;
    private javax.swing.JMenuItem jMenuItem4;
    private javax.swing.JMenuItem jMenuItem6;
    private javax.swing.JMenuItem jMenuItem7;
    private javax.swing.JMenuItem jMenuItem8;
    private javax.swing.JScrollPane jScrollPane1;
    private javax.swing.JScrollPane jScrollPane2;
    private javax.swing.JSeparator jSeparator1;
    private javax.swing.JTextArea jTextArea1;
    private javax.swing.JTextArea jTextArea2;
    // End of variables declaration//GEN-END:variables
}

class CaretAux implements CaretListener {

    int linhaAtual, colunaAtual;

    public CaretAux() {
        linhaAtual = colunaAtual = 0;
    }

    public void caretUpdate(CaretEvent evt) {
        JTextComponent comp = (JTextComponent) evt.getSource();
        JTextArea texto = (JTextArea) ((evt.getSource().getClass().getName().equals("javax.swing.JTextArea"))
                ? evt.getSource() : null);

        int pos = comp.getCaretPosition();
        Element elem = Utilities.getParagraphElement(comp, pos);
        int start = elem.getStartOffset();
        int end = elem.getEndOffset();

        //System.out.println("caretUpdate: " + pos + " " + start + " " + end + " ");
        if (texto != null) {
            String aux = texto.getText();
            int linha = 0;
            for (int i = 0; i < texto.getLineCount(); i++) {
                try {
                    if (start == texto.getLineStartOffset(i)) {
                        linha = i + 1;
                        break;
                    }
                } catch (BadLocationException ex) {
                    Logger.getLogger(CaretAux.class.getName()).log(Level.SEVERE, null, ex);
                }
            }

            linhaAtual = linha;
            colunaAtual = pos - start + 1;

        }
    }
}

class Hora {

    public static final String FORMATO = "[HH:mm:ss]";

    public static String horaAtual() {
        Calendar cal = Calendar.getInstance();
        SimpleDateFormat sdf = new SimpleDateFormat(FORMATO);
        return sdf.format(cal.getTime());

    }
}
